//
// Created by tcj on 2022/3/25.
//

#ifndef _SYLAR_BYTEARRAY_H__
#define _SYLAR_BYTEARRAY_H__

#include "memory"
#include "string"
#include "stdint.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "vector"

namespace sylar{
    class ByteArray{
    public:
        typedef std::shared_ptr<ByteArray> ptr;
        struct Node{
            Node(size_t s);
            Node();
            ~Node();

            char* ptr;
            Node* next;
            size_t size;
        };

        ByteArray(size_t base_size=4096);
        ~ByteArray();

        //write
        void WriteFint8( int8_t value);
        void WriteFuint8( uint8_t  value);
        void WriteFint16( int16_t  value);
        void WriteFuint16( uint16_t  value);
        void WriteFint32( int32_t  value);
        void WriteFuint32( uint32_t  value);
        void WriteFint64( int64_t  value);
        void WriteFuint64( uint64_t  value);


        void WriteInt32( int32_t  value);
        void WriteUint32( uint32_t  value);
        void WriteInt64( int64_t  value);
        void WriteUint64( uint64_t  value);

        void WriteFloat( float  value);
        void WriteDouble( double  value);
        //length:int16,data
        void WriteStringF16(const std::string & value);
        //length:int32 data
        void WriteStringF32(const std::string & value);
        //length:int64 data
        void WriteStringF64(const std::string & value);
        //length:varint data
        void WriteStringVint(const std::string & value);
        //data
        void WirteStringWithoutLength(const std::string& value);


        //read
        int8_t readFint8();
        uint8_t  readFuint8();
        int16_t readFint16();
        uint16_t  readFuint16();
        int32_t readFint32();
        uint32_t  readFuint32();
        int64_t readFint64();
        uint64_t  readFuint64();

        int32_t readInt32();
        uint32_t readUint32();
        int64_t readInt64();
        uint64_t readUint64();

        float  readFloat();
        double readDouble();

        //length:int16,data
        std::string readStringF16();
        //length:int32,data
        std::string readStringF32();
        //length:int64,data
        std::string readStringF64();
        //lengthvarint,data
        std::string readStringVint();

        //内部操作
        void clear();
        void write(const void* buf,size_t size);
        void read(void* buf,size_t size);
        void read(void* buf,size_t size,size_t position) const;

        size_t getPosition() const {return m_position;}
        void setPosition(size_t v);

        bool WriteToFile(const std::string& name) const;
        bool readFromFile(const std::string& name);

        size_t getBaseSize() const{return m_baseSize;}
        size_t getReadSize() const {return m_size - m_position;}

        bool isLittleEndian() const;
        void setLittleEndian(bool val);

        std::string  toString() const;
        std::string toHexString() const;

        //只获取内容，不修改position
        uint32_t getReadBuffer(std::vector<iovec>& buffers,uint64_t len=~0ull) const;
        uint32_t getReadBuffer(std::vector<iovec>& buffers,uint64_t len,uint64_t position) const;
        //增加容量，不修改position
        uint32_t getWriteBuffers(std::vector<iovec>& buffers,uint64_t len);

        size_t getSize() const {return m_size;}
    private:
        void addCapacity(size_t size);
        size_t getCapacity() const {return m_capacity- m_position;}

    private:
        size_t m_baseSize;
        size_t m_position;
        size_t m_capacity;
        size_t m_size;
        int8_t m_endian;

        Node* m_root;
        Node* m_cur;
    };
}

#endif //SERVER_FRAMEWORK_BYTEARRAY_H
